package com.learning.thread.base.threadlocal;

import java.util.Random;

/**
 * ClassName: ThreadLocalObjectData
 * Description: 线程范围内的复杂对象数据共享
 * Date: 2018/6/29 17:38 【需求编号】
 *
 * @author Sam Sho
 * @version V1.0.0
 */
public class ThreadLocalObjectData {


    /**
     * @param args
     */
    public static void main(String[] args) {
        new Thread(new InThread(), "Thread0 ").start();
        new Thread(new InThread(), "Thread1 ").start();
    }

    static class ObjectA {
        public void get() {
            MyNewData myNewData = MyNewData.getThreadInstance();
            System.out.println("A from " + Thread.currentThread().getName() + " get data :" + myNewData);
        }
    }

    static class ObjectB {
        public void get() {
            MyNewData myNewData = MyNewData.getThreadInstance();
            System.out.println("B from " + Thread.currentThread().getName() + " get data :" + myNewData);
        }
    }

    /**
     * 线程一
     */
    static class InThread implements Runnable {

        @Override
        public void run() {
            int data = new Random().nextInt();
            MyNewData myNewData = MyNewData.getThreadInstance();
            myNewData.setAge(data);
            myNewData.setName("name-" + data);

            new ObjectA().get();
            new ObjectB().get();

            myNewData.remove();
        }
    }


    /**
     * ClassName: CustomThread
     * Description: 单例数据 交给数据类的对象
     *
     * <p>
     * Date: 2014-6-29 8:00 【需求编号】
     *
     * @author Sam Sho
     * @version V1.0.0
     */
    static class MyNewData {

        private MyNewData() {
        }

        /**
         * 改造单例，可以不加互斥
         */
        private static ThreadLocal<MyNewData> map = new ThreadLocal<>();

        public static MyNewData getThreadInstance() {
            // ThreadLocal先拿，没有就创建
            MyNewData instance = map.get();
            if (instance == null) {
                instance = new MyNewData();
                // 创建完，就放入ThreadLocal
                map.set(instance);
            }
            return instance;
        }

        public void remove() {
            map.remove();
        }


        private String name;
        private int age;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }

        @Override
        public String toString() {
            return "MyData [age=" + age + ", name=" + name + "]";
        }

    }
}

